package com.cpz.apiversion.config;

import com.cpz.apiversion.annotation.Version;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.resource.ResourceUrlProvider;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;

/**
 * 版本控制
 *
 * @author cpz
 * @since 2022/08/19
 */
@Configuration
public class VersionConfig extends WebMvcConfigurationSupport {

    /**
     * 注解@Version(2)将分发至 /v2/** 默认: /v1/** || /**
     *
     * @param contentNegotiationManager
     * @param conversionService
     * @param resourceUrlProvider
     * @return
     */
    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping(ContentNegotiationManager contentNegotiationManager, FormattingConversionService conversionService, ResourceUrlProvider resourceUrlProvider) {
        return new RequestMappingHandlerMapping() {
            @Override
            protected RequestMappingInfo getMappingForMethod(Method method, Class<?> type) {
                RequestMappingInfo rmi = super.getMappingForMethod(method, type);
                if (Objects.isNull(rmi)) {
                    return null;
                }
                Version version = Optional.ofNullable(AnnotationUtils.findAnnotation(method, Version.class)).orElseGet(() -> AnnotationUtils.findAnnotation(type, Version.class));
                return Objects.nonNull(version)
                        ? RequestMappingInfo.paths(Arrays.stream(version.value()).mapToObj(i -> "v" + i).toArray(String[]::new)).build().combine(rmi)
                        : RequestMappingInfo.paths(new String[]{"v1", ""}).build().combine(rmi);
            }
        };
    }
}

